"""This is module that implements game-specific things"""
__version__ = "$Revision: 68852 $"
# $Source$

import report
import datetime
from sets import Set


"""Enumerations: Please, fixme!"""
NIL = ""
NULL_PLANET = ""
NULL_FLEET = ""

class enum_producing(object):
    """Enum for type of producing on planet"""
    unknown=0
    CAPITAL=1
    RAW=2
    RESEARCH=3
    SHIPS=4


class enum_cargo(object):
    """Enum for type of cargo"""
    #fixme!!!!
    unknown=''
    CAPITAL=1
    RAW=2
    COLONISTS='COL'
    EMPTY='-'


class enum_relationship(object):
    """Enum for type of relationships between players"""
    unknown=0
    WAR=1
    PEACE=2


class enum_state_of_ships(object):
    """Enum for type of relationships between players"""
    unknown = ''
    INORBIT = 'In_Orbit'
    LAUNCHED = 'Launched'
    INSPACE = 'In_Space'
    UPGRADE = 'Upgrade'
    TRANSFER = 'Transfer_Status'


class Tech(object):         #Technologies
    """Class for some technology"""
    def __init__(self, drive = 0, weapons = 0, shields = 0, cargo = 0):
        self.drive = drive
        self.weapons = weapons
        self.shields = shields
        self.cargo = cargo



class Coordinate(object):
    """Class for coordinate"""
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Group_Coordinates(list):
    """Class for coorditates of unindifined groups, it is list"""
    pass


class Planet(object):
    """Class for planet: all about planet"""
    def __init__(self, id, coord, name=NIL, size=NIL, \
            population=NIL, industry=NIL, resources=NIL, \
            producing=NIL, capital=NIL, material=NIL, colonists=NIL,\
            eindustry=NIL):
        """coordinate must be Planet_Coordinate type producing must be Producing type"""
        self.id = id
        self.coord = coord
        self.name = name
        self.size = size
        self.population = population
        self.industry = industry
        self.resources = resources
        self.producing = producing
        self.capital = capital
        self.material = material
        self.colonists = colonists
        self.eindustry = eindustry


class Planets (dict):
    """Simple class that realise set of Planet"""
    def __init__(self):
        # short wrapper around some super (dict) methods
        self._dict_contains = lambda key: \
            super(Planets,self).__contains__(key)
        self._dict_getitem = lambda key: \
            super(Planets,self).__getitem__(key)

    def __getitem__(self, key):
        """Return item; if it not found return item by name"""
        try:
            return self._dict_getitem(key)
        except KeyError:
            if key[0]=='#':
                try:
                    return self._dict_getitem(key[1:])
                except KeyError:
                    print "{E} Error: I can't find planet by #number: ---<<%s>>---" % key
            elif key=='-':
                return NULL_PLANET
            else:
                for i in self:
                    if self._dict_getitem(i).name==key:
                        __isretvalue = 1
                        return self._dict_getitem(i)
                if not __isretvalue:
                    raise KeyError("{E} Error: I can't find planet by #number: ---<<%s>>---" % key)

class Science(object):
    """Class for science"""
    def __init__(self, name, tech):
        """tech must be Tech type"""
        self.name = name
        self.tech = tech


class Sciences(dict):
    """Simple class that realise set of Science"""
    pass


class Route(object):
    """Class for user's route"""
    def __init__(self, from_planet, to_planet, type=enum_cargo.unknown):
        """from_planet and to_planet MUST be Planet type!"""
        self.from_planet = from_planet
        self.to_planet = to_planet
        self.type = type


class Routes(dict):
    """Simple class that realise set of Routes"""
    pass


class Ship_Type(object):
    """Class for ship's type"""
    def __init__(self, name, tech, attacks, mass):
        """tech must be Tech type"""
        self.name = name
        self.tech = tech
        self.attacks = attacks
        self.mass = mass


class Ship_Types(dict):
    """Simple class that realise set of Ship_Type"""
    pass


class Group(object):
    """Class for group: one or many ships of one type and with one parametres"""
    def __init__(self, number_of_ships, ship_type, tech, cargo_type, \
                 cargo_quan, to_planet, per, mass, rest='', from_planet='-', fleet='', \
                 state=enum_state_of_ships.unknown):
        """ship_type must be Ship_Type, tech must be Tech, cargo_type must be \
        enum_cargo, from_planet and to_planet must be Planet, fleet must be Fleet"""
        self.number_of_ships = number_of_ships
        self.ship_type = ship_type
        self.tech = tech
        self.cargo_type = cargo_type
        self.cargo_quan = cargo_quan
        self.to_planet = to_planet
        self.from_planet = from_planet
        self.rest = rest
        self.per = per
        self.mass = mass
        self.fleet = fleet
        self.state = state


class Groups(list):
    """Class for groups: this is set of Group, that NOT IN the any Fleets"""
    pass


class Fleet(dict):
    """Class for fleet: this is set of Group"""
    def __init__(self, id, name, number, destination, origin, \
                 rest, per_turn, state_of_ships=enum_state_of_ships.unknown):
        """destination and origin must be planet, state_of_ships - enum_state_of_ships"""
        self.id = id
        self.name = name
        self.number = number
        self.destination = destination
        self.origin = origin
        self.rest = rest
        self.per_turn = per_turn
        self.state_of_ships = state_of_ships


class Fleets(dict):
    """Class for many fleets this is dict of Fleet"""
    def __init__(self):
        # short wrapper around some super (dict) methods
        self._dict_contains = lambda key: \
            super(Fleets,self).__contains__(key)
        self._dict_getitem = lambda key: \
            super(Fleets,self).__getitem__(key)

    def __getitem__(self, key):
        """Return item; if it not found return item by name"""
        try:
            return self._dict_getitem(key)
        except KeyError:
            if key=='-':
                return NULL_FLEET
            else:
                for i in self:
                    if self._dict_getitem(i).id==key:
                        __isretvalue = 1
                        return self._dict_getitem(i)
                if not __isretvalue:
                    raise KeyError("{E} Error: I can't find fleet by #number: ---<<%s>>---" % key)



class Producing(object):
    """Class for producing type. It is may be Ship_Type, Science or "Resource" string"""
    def __init__(self, producing=""):
        self.name=producing
        if (producing=="raw"):
            self.type=enum_producing.RAW
        if (producing=="capital"):
            self.type=enum_producing.CAPITAL
        if (producing=="research"): #fixme
            self.type=enum_producing.RESEARCH
            #T.O.D.O:search and
            self.producing=0
        if (producing=="ships"): #fixme
            self.type=enum_producing.SHIPS
            self.producing=0 #we must search object that producing //T.O.D.O!

    def __str__(self):
        return self.name


class Bombing(object):
    """Class that implements bombings"""
    def __init__(self, new_owner, planet, planet_id, prev_owner, \
            prev_population, prev_industry, prev_producing, \
            prev_capital, prev_material, prev_colonists, state):
        """new_owner and prev_owner must be Player type, planet must be planet name prev_producing
        must be Producing type"""
        self.new_owner = new_owner
        self.prev_owner = prev_owner
        self.planet = planet
        self.planet_id = planet_id
        self.prev_population = prev_population
        self.prev_industry = prev_industry
        self.prev_producing = prev_producing
        self.prev_capital = prev_capital
        self.prev_material = prev_material
        self.prev_colonists = prev_colonists
        self.state = state


class Bombings(Set):
    """Simple class that realise set of Bombing"""
    pass


class Incoming(object):
    """Class that implements incoming"""
    def __init__(self, origin, destination, remaining, speed, mass):
        """origin and destination must be Planet type"""
        self.origin = origin
        self.destination = destination
        self.remaining = remaining
        self.speed = speed
        self.mass = mass


class Incomings(Set):
    """Simple class that realise set of Incoming"""
    pass





class Player(object):
    """Class for one player"""
    def __init__(self, name, tech, \
            population, industry, numplanets, relationship, votes):
        """tech must be Tech type, relationship must be enum_relationship type"""
        """General player's parametres"""
        self.name = name
        self.tech = tech
        self.population = population
        self.industry = industry
        self.numplanets = numplanets
        self.relationship = relationship
        self.votes = votes
        """Player's groups, planets, ship types and siences"""
        self.groups = Groups()
        self.planets = Planets()
        self.ship_types = Ship_Types()
        self.sciences = Sciences()


class Players(dict):
    """Simple class that realise set of Player"""
    pass


class Galaxy(object):
    """This is global class for galaxy, one object per game!"""
    def __init__(self, report):
        """We parse report"""
        st = 0 #this is counter of strings
        tmp = report[st].split(' ')
        self.player_name = tmp[0]
        self.turn = tmp[tmp.index('Turn')+1]
        self.name = tmp[tmp.index('Turn')-1]
        
        st += 1
        self.server_version = report[st]
        
        st += 2
        tmp = report[st].split(' ')
        self.size =  tmp[tmp.index('Size:')+1]
        self.num_planets =  tmp[tmp.index('Planets:')+1]
        self.num_players =  tmp[tmp.index('Players:')+1]

        self.players = Players()

        st += 2
        print "---broadcast----%s-------" % report[st]
        if 'Broadcast Message' in report[st]:
            st += 2
            while report[st]:
                st += 1
            st += 1
        
        
        
        
        print "---your vote----%s-------" % report[st]
        if 'Your vote:' in report[st]:
            st += 2
            while report[st]:
                st += 1

        st += 1
        if 'Status of Players' in report[st]:
            st += 3
            while report[st]:
                tmp = report[st].split(' ')
                self.players[tmp[0]] = Player(tmp[0], \
                        Tech(tmp[1],tmp[2],tmp[3],tmp[4]), \
                        tmp[5],tmp[6],tmp[7],tmp[8],tmp[9]
                        )

                self.players[tmp[0]].ship_types = Ship_Types()
                st += 1
        
        st += 1
        
        while 'Ship Types' in report[st]:
            tmp = report[st].split(' ')
            if tmp[0]=='Your':
                current_player = self.players[self.player_name]
            else:
                current_player = self.players[tmp[0]]
            st += 3
            while report[st]:
                tmp = report[st].split(' ')
                current_player.ship_types[tmp[0]] = Ship_Type(tmp[0], \
                        Tech(tmp[1],tmp[2],tmp[3],tmp[4]), \
                        tmp[5],tmp[6]
                        )
                st += 1
            st += 1
      
        st += 1

        while 'Battle at' in report[st]:
            print "---batleat- %s ------" % report[st]
            while not ('Battle Protocol' in report[st]):
                st += 1
            print "----batl prot-- %s ------" % report[st]
            st += 2
            while report[st]:
                st += 1
            st += 2
        
        st -= 1
        """fixme!!!! add implementation of battles!!!!"""

        self.bombings = Bombings()
        __tmp_bombings = Set()
        if 'Bombings' in report[st]:
            st += 3
            while report[st]:
                __tmp_bombings.add(report[st])
                st += 1
        
        st += 1
        """fixme! please add implementation of the Bombing object at end!!!!"""


        if 'Map around' in report[st]:
            st += 1
            while not ('--------------------------------------------------' in \
                       report[st]):
                st += 1
            st += 3

        self.incomings = Incomings()
        __tmp_incomings = Set()
        if 'Incoming Groups' in report[st]:
            st += 3
            while report[st]:
                __tmp_incomings.add(report[st])
                st += 1
            st += 1

        
        self.unidentified_planets = Planets()
        self.uninhabited_planets = Planets()
        self.planets = Planets()

        while ('Planets' in report[st]) or ('Ships In Production' in report[st]):
            print "--shipsinprod end- %s ------" % report[st]
            if report[st]=='Ships In Production':
                st += 2
                while report[st]:
                    st += 1
            else:
                tmp = report[st].split(' ')
                if tmp[0]=='Your':
                    current_planets = self.players[self.player_name].planets
                elif tmp[0]=='Unidentified':
                    current_planets = self.unidentified_planets
                elif tmp[0]=='Uninhabited':
                    current_planets = self.uninhabited_planets
                else:
                    current_planets = self.players[tmp[0]].planets
                st += 3
                while report[st]:
                    tmp = report[st].split(' ')
                    if len(tmp)==13:
                        current_planets[tmp[0]]=Planet(tmp[0], \
                                Coordinate(tmp[1],tmp[2]),\
                                tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], \
                                Producing(tmp[8]),\
                                tmp[9], tmp[10],tmp[11], tmp[12]\
                                )
                    elif len(tmp)==8:
                        current_planets[tmp[0]]=Planet(id=tmp[0], \
                                coord=Coordinate(tmp[1],tmp[2]),\
                                name=tmp[3], size=tmp[4], resources=tmp[5], \
                                capital=tmp[6], material=tmp[7]\
                                )
                    elif len(tmp)==3:
                        current_planets[tmp[0]]=Planet(id=tmp[0], \
                                coord=Coordinate(tmp[1],tmp[2]),\
                                )
                    self.planets[tmp[0]]=current_planets[tmp[0]]
                    st += 1
            st += 1
      


        self.fleets = Fleets()
        if 'Your Fleets' in report[st]:
            st += 3
            while report[st]:
                tmp = report[st].split(' ')
                if tmp[3] == '-':
                    __tmp_fleet_planet_destination = '-'
                else:
                    __tmp_fleet_planet_destination = self.planets[tmp[3]]
                if tmp[4] == '-':
                    __tmp_fleet_planet_origin = '-'
                else:
                    __tmp_fleet_planet_origin = self.planets[tmp[4]]
                self.fleets[tmp[1]] = Fleet(tmp[0], tmp[1], tmp[2], \
                        destination=__tmp_fleet_planet_destination, \
                        origin=__tmp_fleet_planet_origin, \
                        rest=tmp[5], per_turn=tmp[6], state_of_ships=tmp[7])
                st += 1
            st += 1
        
        print "--!!---- %s ------" % report[st]

        while 'Groups' in report[st]:
            print "--- %s ------" % report[st]
            tmp = report[st].split(' ')
            if tmp[0]=='Your':
                current_groups = self.players[self.player_name].groups
                current_ship_types = self.players[self.player_name].ship_types
            elif tmp[0]=="Unidentified":
                self.unidentified_groups = Group_Coordinates()
                current_groups = self.unidentified_groups
            else:
                current_groups = self.players[tmp[0]].groups
                current_ship_types = self.players[tmp[0]].ship_types
            st += 3
            while report[st]:
                tmp = report[st].split(' ')
                if len(tmp)==16:
                    """If long string - it about player's own groups"""
                    current_groups.append(Group(number_of_ships=tmp[1], ship_type=current_ship_types[tmp[2]], \
                                             tech=Tech(tmp[3], tmp[4], tmp[5], tmp[6]), \
                                             cargo_type=tmp[7], cargo_quan=tmp[8], \
                                             to_planet=self.planets[tmp[9]], from_planet=self.planets[tmp[10]], \
                                             rest=tmp[11], per=tmp[12], mass=tmp[13], fleet=self.fleets[tmp[14]], \
                                             state=tmp[15]))
                elif len(tmp)==11:
                    """short string - it about another player's group"""
                    current_groups.append(Group(number_of_ships=tmp[0], ship_type=current_ship_types[tmp[1]], \
                                             tech=Tech(tmp[2], tmp[3], tmp[4], tmp[5]), \
                                             cargo_type=tmp[6], cargo_quan=tmp[7], \
                                             to_planet=self.planets[tmp[8]], \
                                             per=tmp[9], mass=tmp[10]))
                elif len(tmp)==2:
                    current_groups.append(Coordinate(tmp[0],tmp[1]))
                    print tmp[0], tmp[1]
                st += 1
            st += 1



        """We write __tmp_ values to appropriate places"""
        for i in __tmp_incomings:
            tmp = i.split(' ')
            self.incomings.add(Incoming(self.planets[tmp[0]], \
                                        self.planets[tmp[1]],tmp[2],tmp[3],tmp[4]))
        for i in __tmp_bombings:
            tmp = i.split(' ')
            self.bombings.add( Bombing(self.players[tmp[0]], \
                                       self.planets[tmp[2]], tmp[2], \
                    self.players[tmp[1]], tmp[4], tmp[5], \
                    Producing(tmp[6]), tmp[7], tmp[8], tmp[9], tmp[10]  ))
    


if __name__=="__main__":
    """Dummy testing :-)))"""



    g = Galaxy(report.Report(report.enum_report_get_method.FILE, file_name="tests/Blood019.rep"));
    for x in  g.incomings:
        print x.__dict__
    """print g.__dict__

    for x in g.players:
        print g.players[x].__dict__
        print g.players[x].tech.__dict__

    print g.players['BloodJazMan'].__dict__
    print g.player_name

    for x in g.players['BloodJazMan'].ship_types:
        print g.players['BloodJazMann'].ship_types[x]
    """
    
    #Plan = Player("Myplanet :)",Tech(1000,23,45),23,234,235,enum_relationship.WAR,1)


    #Plan1 = Player("Myplyer 2 :)",Tech(100,23,45),23,234,235,enum_relationship.PEACE,1)
    #shipptype = Ship_Type("name", Tech(234.234, 5675.78, 123.7645), 767.5, 100000)

    #plans= Players()

    #plans= [Plan,Plan1]

    #print plans[0].__dict__
    #print plans[1].__dict__

    #nauka = Science ("biolohia", 1234, 999, 0, 2)
    #print nauka.__dict__
    #print nauka.tech.__dict__

